package com.zry.demo;

import java.util.EmptyStackException;
import java.util.Stack;

/**
 * 双栈实现队列，每次peek 以及pop 就将左栈弹出到右栈，然后再转移回来。
 * @param <E>
 */
public class StackAsFake<E> {
    private Stack<E> stack = new Stack<E>();
    private Stack<E> stackBak = new Stack<E>();

    private int size = 0;
    private Object lock = new Object();

    public StackAsFake() {

    }

    /**
     * Push element x to the back of queue.
     */
    public void push(E x) {
        synchronized (lock) {
            stack.push(x);
            size++;
        }
    }

    /**
     * Removes the element from in front of queue and returns that element.
     */
    public E pop() {
        synchronized (lock) {
            if (size == 0) {
                throw new EmptyStackException();
            }

            if (size == 1) {
                size--;
                return stack.pop();
            } else {
                while (size > 1) {
                    stackBak.add(stack.pop());
                    size--;
                }
                E result = stack.pop();
                size--;
                while (stackBak.size() > 0) {
                    stack.add(stackBak.pop());
                    size++;
                }
                return result;
            }
        }
    }

    /**
     * Get the front element.
     */
    public E peek() {
        synchronized (lock){
            if (size == 0) {
                throw new EmptyStackException();
            }

            if (size == 1) {
                return stack.peek();
            } else {
                while (size > 1) {
                    stackBak.add(stack.pop());
                    size--;
                }
                E result = stack.peek();
                while (stackBak.size() > 0) {
                    stack.add(stackBak.pop());
                    size++;
                }
                return result;
            }
        }
    }

    /**
     * Returns whether the queue is empty.
     */
    public boolean empty() {
        synchronized (lock){
            return size == 0;
        }
    }

    public static void main(String[] args) {
        StackAsFake<Integer> stackAsFake = new StackAsFake<>();
        stackAsFake.push(10);
        stackAsFake.push(20);

        int peek = stackAsFake.peek();
        System.out.println("peek=" + peek);

        int pop = stackAsFake.pop();
        System.out.println("pop=" + pop);

        int pop2 = stackAsFake.pop();
        System.out.println("pop2=" + pop2);

        boolean isEmpty = stackAsFake.empty();
        System.out.println("isEmpty=" + isEmpty);
    }
}
